#ifndef _norm_1_impl_hpp_
#define _norm_1_impl_hpp_

#include <numeric>
#include <cmath>

#include "../math_traits.hpp"
#include "../vector_traits.hpp"

#include "../accumulate.hpp"
#include "../aux_functional.hpp"

namespace core {

    namespace math {

        namespace detail {

            template<class T>
                struct norm_1_scalar_impl
                {
                    static T eval(const T& v)
                    {
                        using std::abs;
                        return abs(v);
                    }
                };

            template<class V>
                struct norm_1_vector_impl
                {
                    typedef typename field<V>::type scalar_type;
                    static typename field<V>::type eval(const V& v)
                    {
                        return accumulate(v,scalar_type(0),aux::plus_abs<scalar_type>());
                    }
                };

            template<class T>
                struct choose_norm_1_impl
                :   public boost::mpl::eval_if_c<is_scalar<T>::value,
                                                boost::mpl::identity<norm_1_scalar_impl<T> >,
                                                boost::mpl::identity<norm_1_vector_impl<T> >
                                                >
                { };
        } // namespace detail

    } // namespace vector

} // namespace math

#endif // _norm_1_impl_hpp_
